/*****************************************************************************
 *   adc.c:  ADC module file for NXP LPC23xx Family Microprocessors
 *
 *   Copyright(C) 2006, NXP Semiconductor
 *   All rights reserved.
 *
 *   History
 *   2006.08.15  ver 1.00    Prelimnary version, first Release
 *
******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
#include <nxp/iolpc2378.h>

#include "irq.h"
#include "target.h"
#include "adc.h"
#include "i2c.h"
#include <intrinsics.h>
#include <string.h>

 #include "FreeRTOS.h"
 #include "task.h"
volatile DWORD ADC0Value[ADC_NUM];
volatile DWORD ADC0IntDone = 0;

#if ADC_INTERRUPT_FLAG
/******************************************************************************
** Function name:   ADC0Handler
**
** Descriptions:    ADC0 interrupt handler
**
** parameters:      None
** Returned value:    None
**
******************************************************************************/
__irq __nested __arm void ADC0Handler (void)
{
DWORD regVal;

  __enable_interrupt();       /* handles nested interrupt */

  regVal = ADSTAT;            /* Read ADC will clear the interrupt */
  if ( regVal & 0x0000FF00 )  /* check OVERRUN error first */
  {
    regVal = (regVal & 0x0000FF00) >> 0x08;
    /* if overrun, just read ADDR to clear */
    /* regVal variable has been reused. */
    switch ( regVal )
    {
    case 0x01:
      regVal = ADDR0;
      break;
    case 0x02:
      regVal = ADDR1;
      break;
    case 0x04:
      regVal = ADDR2;
      break;
    case 0x08:
      regVal = ADDR3;
      break;
    case 0x10:
      regVal = ADDR4;
      break;
    case 0x20:
      regVal = ADDR5;
      break;
    case 0x40:
      regVal = ADDR6;
      break;
    case 0x80:
      regVal = ADDR7;
      break;
    default:
      break;
    }
    AD0CR &= 0xF8FFFFFF;  /* stop ADC now */
    ADC0IntDone = 1;
    return;
  }

  if ( regVal & ADC_ADINT )
  {
    switch ( regVal & 0xFF )  /* check DONE bit */
    {
    case 0x01:
      ADC0Value[0] = ( ADDR0 >> 6 ) & 0x3FF;
      break;
    case 0x02:
      ADC0Value[1] = ( ADDR1 >> 6 ) & 0x3FF;
      break;
    case 0x04:
      ADC0Value[2] = ( ADDR2 >> 6 ) & 0x3FF;
      break;
    case 0x08:
      ADC0Value[3] = ( ADDR3 >> 6 ) & 0x3FF;
      break;
    case 0x10:
      ADC0Value[4] = ( ADDR4 >> 6 ) & 0x3FF;
      break;
    case 0x20:
      ADC0Value[5] = ( ADDR5 >> 6 ) & 0x3FF;
      break;
    case 0x40:
      ADC0Value[6] = ( ADDR6 >> 6 ) & 0x3FF;
      break;
    case 0x80:
      ADC0Value[7] = ( ADDR7 >> 6 ) & 0x3FF;
      break;
    default:
      break;
    }
    AD0CR &= 0xF8FFFFFF;  /* stop ADC now */
    ADC0IntDone = 1;
  }

  VICADDRESS = 0;   /* Acknowledge Interrupt */
}
#endif

/*****************************************************************************
** Function name:   ADCInit
**
** Descriptions:    initialize ADC channel
**
** parameters:      ADC clock rate
** Returned value:    true or false
**
*****************************************************************************/
DWORD ADCInit()
{
  /* Enable CLOCK into ADC controller */
  PCONP |= (1 << 12);

  /* all the related pins are set to ADC inputs, AD0.0~7 */
 // PINSEL0 |= 0x0F000000;  /* P0.12~13, A0.6~7, function 11 */
 // PINSEL1 &= ~0x003FC000; /* P0.23~26, A0.0~3, function 01 */
            
    PINSEL1 |= 0x00054000;//0x00040000;
    //PINSEL1 |=(1<<23);
  
//  PINSEL3 |= 0xF0000000;  /* P1.30~31, A0.4~5, function 11 */

  AD0CR = ( 0x01 << 0 ) |   /* SEL=1,select channel 0~7 on ADC0 */
          ( ( Fpclk / 1000000 - 1 ) << 8 ) |  /* CLKDIV = Fpclk / 1000000 - 1 */
          ( 0 << 16 ) |     /* BURST = 0, no BURST, software controlled */
          ( 0 << 17 ) |     /* CLKS = 0, 11 clocks/10 bits */
          ( 1 << 21 ) |     /* PDN = 1, normal operation */
          ( 0 << 22 ) |     /* TEST1:0 = 00 */
          ( 0 << 24 ) |     /* START = 0 A/D conversion stops */
          ( 0 << 27 );      /* EDGE = 0 (CAP/MAT singal falling,trigger A/D conversion) */

  /* If POLLING, no need to do the following */
 /*
#if ADC_INTERRUPT_FLAG
  
  ADINTEN = 0x1FF;    // Enable all interrupts //
  if ( install_irq( ADC0_INT, (void *)ADC0Handler, HIGHEST_PRIORITY ) == FALSE )
  {
    return (FALSE);
  }
  
#endif
   */
  
  return (TRUE);
}

/*****************************************************************************
** Function name:   ADC0Read
**
** Descriptions:    Read ADC0 channel
**
** parameters:      Channel number
** Returned value:    Value read, if interrupt driven, return channel #
**
*****************************************************************************/
DWORD ADC0Read( int channelNum )
{
   unsigned int value;
    if ( channelNum >= 7 ) { channelNum = 0; }

    AD0CR &= 0xFFFFFF00;
//    AD0CR |= (1 << AD0CR_START_BIT) | (1 << channelNum);   // switch channel,start A/D convert
    AD0CR |= (1 << channelNum);   // switch channel
     vTaskDelay(1);
    //delay_us(100);                // delay for charge ADC-capacitor
    AD0CR |= (1 << AD0CR_START_BIT);   // start A/D convert

    for (char j = 0; j < 0xFF; j++)
    {
      value = AD0GDR;
      if (value & AD0GDR_DONE_MASK) break;
      for (volatile char i = 0; i < 0xFF; i++);
    }

    AD0CR &= ~(1<<AD0CR_START_BIT);//0xF8FFFFFF;            // stop ADC now     
    value >>= 6; 
    value &= 0x3FF;
              // return A/D conversion value
 
  return value;
}


void adc_disable()
{
  // Stop conversion
  AD0CR &= ~(1<<AD0CR_START_BIT);
  // Disable ADC
  AD0CR &= ~(1<<AD0CR_PDN_BIT);
  // Power off
  PCONP &= ~(1<<PCONP_PCAD_BIT);
}


/*********************************************************************************
**                            End Of File
*********************************************************************************/
int Convert_TEMP(unsigned int value)
{

           static float ref = 6.25;
           static float ref1 = 2.5;
           static float ref2 = 2.5;
           float adc = 0;
           int i = 8;
           int CTEMP;
        int CTEMP2;
         CTEMP2=ADC0Read(2); 
          CTEMP = ((2500*CTEMP2/1024)-424)/ref;
       //     ain[8]=CTEMP;
 return CTEMP;
   
            CTEMP2=ADC0Read(0);
            
            CTEMP = 7*ref1*CTEMP2/1024;
            ain[7]=CTEMP;
            
            
            CTEMP2=ADC0Read(1);
            CTEMP = 6*ref1*CTEMP2/1024;
            ain[9]=CTEMP;          
            
          
      //  for (int i = 0; i < AIN_COUNT - 2; i++) {
  //    AIN_SELECT(i);

      
       //   adc=((ADC0Read(2)*400)/ref) - 68;
          
     /* for (int j = 0; j < 10; j++) 
      {
        
       
        
       adc += ((float)ADC0Read(2));
     
      
      if      (adc > 0.0  && adc < 60)  adc /= 0.14765000;
      else if (adc >= 60  && adc < 123) adc /= 0.15360417;
      else if (adc >= 123 && adc < 186) adc /= 0.15360417;
      else if (adc >= 186 && adc < 248) adc /= 0.15465278;
      else if (adc >= 248)              adc /= 0.15539583;
      ain[i] = adc;
      
      }
   // } */
          
     // ain[0] = ((ADC0Read(2)*400)/ref) - 68; 
      
     // CTEMP=snprintf(&CTEMP, 512, "%d,", ain[0]);
        
      
   //   modem_debug(CTEMP); 
}
#ifdef __cplusplus
}
#endif
